// Copyright 2020 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: DServer support simple entity
// feature: support auth token
// feature: provide query interfaces
// feature: develop dispatcher
// feature: Unified Transport Abstraction Layer Unified Transport Abstraction Layer
// feature: discovery support client and server
// feature: add dynamic type lookup service
// ------------------------------------------------------------------

#ifndef INCLUDE_EDDS_RTPS_BUILTIN_DISCOVERY_PARTICIPANT_PDP_H_
#define INCLUDE_EDDS_RTPS_BUILTIN_DISCOVERY_PARTICIPANT_PDP_H_
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

#include <edds/rtps/participant/RTPSParticipant.h>
#include <edds/rtps/attributes/RTPSParticipantAttributes.h>
#include <edds/rtps/builtin/data/ReaderProxyData.h>
#include <edds/rtps/builtin/data/WriterProxyData.h>
#include <edds/rtps/common/Guid.h>
#include <edds/rtps/participant/ParticipantDiscoveryInfo.h>
#include <ertps/qos/QosPolicies.h>
#include <discovery/participant/PDPEndpoints.hpp>

#include <atomic>
#include <mutex>
#include <functional>

#include <ertps/utils/ProxyPool.hpp>
#include <ertps/utils/collections/ResourceLimitedVector.hpp>

#include <discovery/database/DiscoveryEndpointInfo.hpp>
#include <discovery/database/DiscoveryParticipantInfo.hpp>
#if HAVE_SECURITY
#include <rtps/security/SecurityManager.h>
#endif

namespace vbs {
namespace common {
class TimedEvent;
class ParticipantListener;
class ReaderHistory;
class WriterHistory;
class ReaderListener;
class ITopicPayloadPool;

// Restart timer delay in milliseconds
#define PDP_RESTART_TIMER_DELAY 5

}  // namespace common
}  // namespace vbs
namespace evbs {

namespace edds {
namespace rtps {

class PDPServerListener;

}  // namespace rtps
}  // namespace edds

namespace ertps {
namespace rtps {

using namespace evbs::ertps::rtps::ddb;

class RTPSWriter;
class RTPSReader;
class RTPSParticipantImpl;

class BuiltinProtocols;
class EDP;
class ReaderProxyData;
class WriterProxyData;
class ParticipantProxyData;

class PDPListener;
class PDPServerListener;
class PDPEndpoints;

/**
 * Abstract class PDP that implements the basic interfaces for all Participant Discovery
 *implementations It also keeps the Participant Discovery Data and provides interfaces to access it
 *@ingroup DISCOVERY_MODULE
 */
class PDP {
    friend class PDPListener;
    friend class PDPServerListener;
    friend class PDPServerCompatibleListener;
    friend class edds::rtps::PDPServerListener;
#if HAVE_SECURITY
    friend class PDPSecurityInitiatorListener;
    friend class security::SecurityManager;
#endif

 public:
    /**
     * Constructor
     * @param builtin Pointer to the BuiltinProcols object.
     * @param allocation Participant allocation parameters.
     */
    PDP(BuiltinProtocols* builtin, const RTPSParticipantAllocationAttributes& allocation);

    virtual ~PDP();

    virtual void initializeParticipantProxyData(ParticipantProxyData* participant_data);

    /**
     * Initialize the PDP.
     * @param part Pointer to the RTPSParticipant.
     * @return True on success
     */
    bool initPDP(RTPSParticipantImpl* part);

    /**
     * @brief Enable the Participant Discovery Protocol
     *
     * @return true if enabled correctly, or if already enabled; false otherwise
     */
    bool enable();

    virtual bool init(RTPSParticipantImpl* part) = 0;

    /**
     * @brief Perform actions before enabling the Participant Discovery Protocol if needed
     */
    virtual void pre_enable_actions();

    /**
     * @brief Disable the Participant Discovery Protocol
     */
    void disable();

    /**
     * Creates an initializes a new participant proxy from a DATA(p) raw info
     * @param p from DATA msg deserialization
     * @param writer_guid GUID of originating writer
     * @return new ParticipantProxyData * or nullptr on failure
     */
    virtual ParticipantProxyData* createParticipantProxyData(const ParticipantProxyData& p,
                                                             const GUID_t& writer_guid) = 0;

    /**
     * Force the sending of our local DPD to all remote RTPSParticipants and multicast Locators.
     * @param new_change If true a new change (with new seqNum) is created and sent;If false the
     * last change is re-sent
     * @param dispose sets change kind to NOT_ALIVE_DISPOSED_UNREGISTERED
     * @param wparams allows to identify the change
     */
    virtual void announceParticipantState(bool new_change, bool dispose, WriteParams& wparams) = 0;
    /**
     * \c announceParticipantState method without optional output parameter \c wparams .
     */
    virtual void announceParticipantState(bool new_change, bool dispose = false);

    //! Stop the RTPSParticipantAnnouncement (only used in tests).
    virtual void stopParticipantAnnouncement();

    //! Reset the RTPSParticipantAnnouncement (only used in tests).
    virtual void resetParticipantAnnouncement();

    /**
     * Add a ReaderProxyData to the correct ParticipantProxyData.
     * @param [in]  reader_guid       GUID of the reader to add.
     * @param [out] participant_guid  GUID of the ParticipantProxyData where the reader was added.
     * @param [in]  initializer_func  Function to be called in order to set the data of the
     * ReaderProxyData.
     *
     * @return A pointer to the added ReaderProxyData (nullptr if it could not be added).
     */
    ReaderProxyData* addReaderProxyData(
        const GUID_t& reader_guid, GUID_t& participant_guid,
        std::function<bool(ReaderProxyData*, bool, const ParticipantProxyData&, RTPSParticipantImpl*)>
            initializer_func);

    /**
     * Add a WriterProxyData to the correct ParticipantProxyData.
     * @param [in]  writer_guid       GUID of the writer to add.
     * @param [out] participant_guid  GUID of the ParticipantProxyData where the writer was added.
     * @param [in]  initializer_func  Function to be called in order to set the data of the
     * WriterProxyData.
     *
     * @return A pointer to the added WriterProxyData (nullptr if it could not be added).
     */
    WriterProxyData* addWriterProxyData(
        const GUID_t& writer_guid, GUID_t& participant_guid,
        std::function<bool(WriterProxyData*, bool, const ParticipantProxyData&, RTPSParticipantImpl*)>
            initializer_func);

    /**
     * This method returns whether a ReaderProxyDataObject exists among the registered
     * RTPSParticipants (including the local RTPSParticipant).
     * @param [in] reader GUID_t of the reader we are looking for.
     * @return True if found.
     */
    bool has_reader_proxy_data(const GUID_t& reader);

    /**
     * This method gets a copy of a ReaderProxyData object if it is found among the registered
     * RTPSParticipants (including the local RTPSParticipant).
     * @param [in]  reader  GUID_t of the reader we are looking for.
     * @param [out] rdata   Reference to the ReaderProxyData object where data is to be returned.
     * @return True if found.
     */
    bool lookupReaderProxyData(const GUID_t& reader, ReaderProxyData& rdata);

    /**
     * This method returns whether a WriterProxyData exists among the registered RTPSParticipants
     * (including the local RTPSParticipant).
     * @param [in] writer GUID_t of the writer we are looking for.
     * @return True if found.
     */
    bool has_writer_proxy_data(const GUID_t& writer);

    /**
     * This method gets a copy of a WriterProxyData object if it is found among the registered
     * RTPSParticipants (including the local RTPSParticipant).
     * @param [in]  writer  GUID_t of the writer we are looking for.
     * @param [out] wdata   Reference to the WriterProxyData object where data is to be returned.
     * @return True if found.
     */
    bool lookupWriterProxyData(const GUID_t& writer, WriterProxyData& wdata);

    /**
     * This method returns the name of a participant if it is found among the registered
     * RTPSParticipants.
     * @param [in]  guid  GUID_t of the RTPSParticipant we are looking for.
     * @param [out] name  Copy of name on ParticipantProxyData object.
     * @return True if found.
     */
    bool lookup_participant_name(const GUID_t& guid, string_255& name);

    /**
     * This method removes and deletes a ReaderProxyData object from its corresponding
     * RTPSParticipant.
     * @param reader_guid GUID_t of the reader to remove.
     * @return true if found and deleted.
     */
    bool removeReaderProxyData(const GUID_t& reader_guid);

    /**
     * This method removes and deletes a WriterProxyData object from its corresponding
     * RTPSParticipant.
     * @param writer_guid GUID_t of the wtiter to remove.
     * @return true if found and deleted.
     */
    bool removeWriterProxyData(const GUID_t& writer_guid);

    /**
     * Create the SPDP Writer and Reader
     * @return True if correct.
     */
    virtual bool createPDPEndpoints() = 0;

    /**
     * This method assigns remote endpoints to the builtin endpoints defined in this protocol. It
     * also calls the corresponding methods in EDP and WLP.
     * @param pdata Pointer to the RTPSParticipantProxyData object.
     */
    virtual void assignRemoteEndpoints(ParticipantProxyData* pdata) = 0;

    /**
     * Override to match additional endpoints to PDP. Like EDP or WLP.
     * @param pdata Pointer to the ParticipantProxyData object.
     */
    virtual void notifyAboveRemoteEndpoints(const ParticipantProxyData& pdata, bool notify_secure_endpoints) = 0;

    /**
     * Some PDP classes require EDP matching with update PDP DATAs like EDPStatic
     * @return true if EDP endpoinst must be match
     */
    virtual bool updateInfoMatchesEDP() { return false; }

    /**
     * Remove remote endpoints from the participant discovery protocol
     * @param pdata Pointer to the ParticipantProxyData to remove
     */
    virtual void removeRemoteEndpoints(ParticipantProxyData* pdata) = 0;

    /**
     * This method removes a remote RTPSParticipant and all its writers and readers.
     * @param participant_guid GUID_t of the remote RTPSParticipant.
     * @param reason Why the participant is being removed (dropped vs removed)
     * @return true if correct.
     */
    virtual bool remove_remote_participant(const GUID_t& participant_guid,
                                           ParticipantDiscoveryInfo::DISCOVERY_STATUS reason);

    /**
     * This method returns the BuiltinAttributes of the local participant.
     * @return const reference to the BuiltinAttributes of the local participant.
     */
    const BuiltinAttributes& builtin_attributes() const;

    /**
     * Get a pointer to the local RTPSParticipant ParticipantProxyData object.
     * @return Pointer to the local RTPSParticipant ParticipantProxyData object.
     */
    ParticipantProxyData* getLocalParticipantProxyData() const {
        return participant_proxies_.empty() ? nullptr : participant_proxies_.front();
    }

    /**
     * Get a pointer to the EDP object.
     * @return pointer to the EDP object.
     */
    inline EDP* getEDP() { return mp_EDP; }

    /**
     * Get a const_iterator to the beginning of the RTPSParticipant Proxies.
     * @return const_iterator.
     */
    ResourceLimitedVector<ParticipantProxyData*>::const_iterator ParticipantProxiesBegin() {
        return participant_proxies_.begin();
    }

    /**
     * Get a const_iterator to the end of the RTPSParticipant Proxies.
     * @return const_iterator.
     */
    ResourceLimitedVector<ParticipantProxyData*>::const_iterator ParticipantProxiesEnd() {
        return participant_proxies_.end();
    }

    /**
     * Get the number of participant proxies.
     * @return size_t.
     */
    size_t participant_proxies_number() { return participant_proxies_number_; }

    /**
     * Assert the liveliness of a Remote Participant.
     * @param remote_guid GuidPrefix_t of the participant whose liveliness is being asserted.
     */
    void assert_remote_participant_liveliness(const GuidPrefix_t& remote_guid);

    /**
     * Get the RTPS participant
     * @return RTPS participant
     */
    inline RTPSParticipantImpl* getRTPSParticipant() const { return mp_RTPSParticipant; }

    /**
     * Get the mutex.
     * @return Pointer to the Mutex
     */
    inline std::recursive_mutex* getMutex() const { return mp_mutex; }

    CDRMessage_t get_participant_proxy_data_serialized(Endianness_t endian);

    /**
     * Retrive the ParticipantProxyData of a participant
     * @param guid_prefix The GUID prefix of the participant of which the proxy data is retrieved
     * @return A pointer to the ParticipantProxyData. nullptr if there is no such
     * ParticipantProxyData
     */
    ParticipantProxyData* get_participant_proxy_data(const GuidPrefix_t& guid_prefix);

    /**
     * Get the list of remote servers' locators to which the participant should connect
     * @return A reference to the LocatorList
     */
    LocatorList_t& remote_server_locators();

    /**
     * Access the temporary proxy pool for reader proxies
     * @return pool reference
     */
    ProxyPool<ReaderProxyData>& get_temporary_reader_proxies_pool() { return temp_reader_proxies_; }

    /**
     * Access the temporary proxy pool for writer proxies
     * @return pool reference
     */
    ProxyPool<WriterProxyData>& get_temporary_writer_proxies_pool() { return temp_writer_proxies_; }

    ReaderAttributes create_builtin_reader_attributes() const;

    WriterAttributes create_builtin_writer_attributes() const;

#if HAVE_SECURITY
    void add_builtin_security_attributes(ReaderAttributes& ratt, WriterAttributes& watt) const;

    virtual bool pairing_remote_writer_with_local_reader_after_security(const GUID_t& local_reader,
                                                                        const WriterProxyData& remote_writer_data);

    virtual bool pairing_remote_reader_with_local_writer_after_security(const GUID_t& local_writer,
                                                                        const ReaderProxyData& remote_reader_data);
#endif  // HAVE_SECURITY

    // bool get_all_local_proxies(std::vector<GUID_t>&) override { return false; }

    // bool get_serialized_proxy(const GUID_t&, CDRMessage_t*) override { return false; }

    /**
     * Start to send announcement message with initial announcement period
     * @return void
     */
    void start_initial_announcement(uint32_t count, Duration_t period);

    // RTPSWriter* PDPWriter() const { return builtin_endpoints_->writer; }
    //! get is_send_multi
    bool getSendMulti() const;

    //! set is_send_multi
    void setSendMulti(bool send_multi);

    EvbsVersion_t get_version_by_guid(const GuidPrefix_t& guid_prefix);

    // Get all the participants in DataBase
    virtual bool get_participants_in_db(std::vector<GuidPrefix_t>& prefix_list) {  //LCOV_EXCL_START
        (void)prefix_list;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    };

    // Get the participant info by guid_prefix
    virtual bool get_participant_info(const GuidPrefix_t& prefix, DiscoveryParticipantInfo& part_info) {
        (void)prefix;
        (void)part_info;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    };

    // Get the reader info by guid
    virtual bool get_reader_info(const GUID_t& reader_guid, DiscoveryEndpointInfo& reader_info) {
        (void)reader_guid;
        (void)reader_info;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    };

    // Get the writer info by guid
    virtual bool get_writer_info(const GUID_t& writer_guid, DiscoveryEndpointInfo& writer_info) {
        (void)writer_guid;
        (void)writer_info;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    };

    virtual bool get_topic_names(std::vector<std::string>& topic_list) {
        (void)topic_list;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    }

    virtual bool has_writer(const std::string& topic_name) {
        (void)topic_name;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    }

    virtual bool has_reader(const std::string& topic_name) {
        (void)topic_name;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    }

    virtual bool get_writer_of_topic(const std::string& topic_name,
                                     std::vector<DiscoveryEndpointInfo>& writer_info_list) {
        (void)topic_name;
        (void)writer_info_list;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    }

    virtual bool get_reader_of_topic(const std::string& topic_name,
                                     std::vector<DiscoveryEndpointInfo>& reader_info_list) {
        (void)topic_name;
        (void)reader_info_list;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    }

    virtual bool has_participant(const std::string& participant_name) {
        (void)participant_name;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    }

    virtual bool get_participant_of_name(const std::string& participant_name, DiscoveryParticipantInfo& part_info) {
        (void)participant_name;
        (void)part_info;
        elogWarning(RTPS_PDP, "The entity is not DServer.");
        return false;
    }  //LCOV_EXCL_STOP
    void remove_remote_all_entities(ParticipantProxyData* pdata, const GUID_t& partGUID,
                                    ParticipantDiscoveryInfo::DISCOVERY_STATUS reason, ParticipantListener* listener);
    bool lookup_participant_locators(const GuidPrefix_t& guid_prefix, LocatorList_t& locators);

    virtual void remove_monitored_guid(const GUID_t& partGUID) { (void)partGUID; }

 protected:
    //! Pointer to the builtin protocols object.
    BuiltinProtocols* mp_builtin;
    //! Pointer to the local RTPSParticipant.
    RTPSParticipantImpl* mp_RTPSParticipant;
    //! Discovery attributes.
    BuiltinAttributes m_discovery;
    //! Builtin PDP endpoints
    std::unique_ptr<evbs::ertps::rtps::PDPEndpoints> builtin_endpoints_;
    //! Pointer to the EDP object.
    EDP* mp_EDP;
    //! Number of participant proxy data objects created
    size_t participant_proxies_number_;
    //! Registered RTPSParticipants (including the local one, that is the first one.)
    ResourceLimitedVector<ParticipantProxyData*> participant_proxies_;
    //! Deleting RTPSParticipants (including the deleting one.)
    ResourceLimitedVector<ParticipantProxyData*> participant_deleting_proxies_;
    //! Pool of participant proxy data objects ready for reuse
    ResourceLimitedVector<ParticipantProxyData*> participant_proxies_pool_;
    //! Number of reader proxy data objects created
    size_t reader_proxies_number_;
    //! Pool of reader proxy data objects ready for reuse
    ResourceLimitedVector<ReaderProxyData*> reader_proxies_pool_;
    //! Number of writer proxy data objects created
    size_t writer_proxies_number_;
    //! Pool of writer proxy data objects ready for reuse
    ResourceLimitedVector<WriterProxyData*> writer_proxies_pool_;
    //! Variable to indicate if any parameter has changed.
    std::atomic_bool m_hasChangedLocalPDP;
    //! Writer payload pool
    std::shared_ptr<vbs::common::ITopicPayloadPool> writer_payload_pool_;
    //! Reader payload pool
    std::shared_ptr<vbs::common::ITopicPayloadPool> reader_payload_pool_;
    //! ProxyPool for temporary reader proxies
    ProxyPool<ReaderProxyData> temp_reader_proxies_;
    //! ProxyPool for temporary writer proxies
    ProxyPool<WriterProxyData> temp_writer_proxies_;
    //! Participant data atomic access assurance
    std::recursive_mutex* mp_mutex;
    //! To protect callbacks (ParticipantProxyData&)
    std::mutex callback_mtx_;
    //! Tell if object is enabled
    std::atomic<bool> enabled_ {false};
    //! startTime mapping table atomic access assurance
    std::recursive_mutex* startTime_mutex;
    std::unordered_map<GuidPrefix_t, Time_t> pdata_startTime;
    //! Record the correspondence between client forwarded by server
    std::unordered_map<GUID_t, GuidPrefix_t> client_by_server;
    /**
     * Adds an entry to the collection of participant proxy information.
     * May use one of the entries present in the pool.
     *
     * @param participant_guid GUID of the participant for which to create the proxy object.
     * @param with_lease_duration indicates whether lease duration event should be created.
     * @param participant_proxy_data The participant proxy data from which the copy is made (if
     * provided)
     *
     * @return pointer to the currently inserted entry, nullptr if allocation limits were reached.
     */
    ParticipantProxyData* add_participant_proxy_data(const GUID_t& participant_guid, bool with_lease_duration,
                                                     const Time_t& startTime,
                                                     const ParticipantProxyData* participant_proxy_data = nullptr);

    /**
     * Checks whether two participant prefixes are equal by calculating the mangled
     * GUID and comparing it with the remote participant prefix.
     *
     * @param guid_prefix the original desired guid_prefix to compare
     * @param participant_data The participant proxy data to compare against
     *
     * @return true when prefixes are equivalent
     */
    bool data_matches_with_prefix(const GuidPrefix_t& guid_prefix, const ParticipantProxyData& participant_data);

    /**
     * Obtains the participant type based on a Parameters Properties list.
     *
     * @param properties Parameter Properties list to check
     *
     * @return a string indicating the participant type.
     */
    std::string check_participant_type(const edds::dds::ParameterPropertyList_t properties);

    /**
     * Gets the key of a participant proxy data.
     *
     * @param [in] participant_guid GUID of the participant to look for.
     * @param [out] key of the corresponding proxy object.
     *
     * @return true when input GUID is found.
     */
    bool lookup_participant_key(const GUID_t& participant_guid, InstanceHandle_t& key);
    /**
     * Force the sending of our local DPD to all remote RTPSParticipants and multicast Locators.
     * @param history history where the change should be added
     * @param new_change If true a new change (with new seqNum) is created and sent;If false the last change is re-sent
     * @param dispose sets change kind to NOT_ALIVE_DISPOSED_UNREGISTERED
     * @param wparams allows to identify the change
     */
    void announceParticipantState(WriterHistory& history, bool new_change, bool dispose = false,
                                  WriteParams& wparams = WriteParams::WRITE_PARAM_DEFAULT);

    /**
     * Called after creating the builtin endpoints to update the metatraffic unicast locators of BuiltinProtocols
     */
    virtual void update_builtin_locators() = 0;

    void notify_and_maybe_ignore_new_participant(ParticipantProxyData* pdata, bool& should_be_ignored);

    /**
     * Restores the `initial_announcements_` configuration to resend the initial announcements again.
     */
    void resend_ininitial_announcements();

    void update_guid_startTime(GuidPrefix_t guidPrefix, Time_t startTime) {
        std::lock_guard<std::recursive_mutex> lock(*startTime_mutex);
        pdata_startTime[guidPrefix] = startTime;
    }

 private:
    //! TimedEvent to periodically resend the local RTPSParticipant information.
    vbs::common::TimedEvent* resend_participant_info_event_;

    //! Participant's initial announcements config
    InitialAnnouncementConfig initial_announcements_;

    void check_remote_participant_liveliness(ParticipantProxyData* remote_participant);

    void check_and_notify_type_discovery(vbs::common::ParticipantListener* listener,
                                         const WriterProxyData& wdata) const;

    void check_and_notify_type_discovery(vbs::common::ParticipantListener* listener,
                                         const ReaderProxyData& rdata) const;

    /**
     * Calculates the next announcement interval
     */
    void set_next_announcement_interval();

    /**
     * Calculates the initial announcement interval
     */
    void set_initial_announcement_interval();

    /**
     * Set to a Participant Proxy those properties from this participant that must be sent.
     */
    void set_external_participant_properties_(ParticipantProxyData* participant_data);

    /**
     * Performs all the necessary actions after removing a ParticipantProxyData from the
     * participant_proxies_ collection.
     *
     * @param pdata ParticipantProxyData that was removed.
     * @param partGUID GUID of the removed participant.
     * @param reason Reason why the participant was removed.
     * @param listener Listener to be notified of the unmatches / removal.
     */
    void actions_on_remote_participant_removed(ParticipantProxyData* pdata, const GUID_t& partGUID,
                                               ParticipantDiscoveryInfo::DISCOVERY_STATUS reason,
                                               vbs::common::ParticipantListener* listener);
};

// configuration values for PDP reliable entities.
extern const Duration_t pdp_heartbeat_period;
extern const Duration_t pdp_nack_response_delay;
extern const Duration_t pdp_nack_supression_duration;
extern const Duration_t pdp_heartbeat_response_delay;

extern const int32_t pdp_initial_reserved_caches;

} /* namespace rtps */
} /* namespace ertps */
} /* namespace evbs */

#endif  // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
#endif  // INCLUDE_EDDS_RTPS_BUILTIN_DISCOVERY_PARTICIPANT_PDP_H_
